package cn.geckos.ioc.parsing
{
	import flexunit.framework.TestCase;
	import flexunit.framework.TestSuite;
	
	import flash.utils.Dictionary;
	
	import cn.geckos.ioc.parsing.XMLConfigParser;
	import cn.geckos.ioc.factory.Bean;
	import cn.geckos.mock.PlainTest;
	import cn.geckos.ioc.parsing.Scope;
	import cn.geckos.mock.ReferenceTypeMock;
	import cn.geckos.mock.MapMock;
	import cn.geckos.mock.StackMock;
	import cn.geckos.fml.data.StackData;
	import cn.geckos.mock.InitMock;

	public class ParsingTest extends TestCase
	{
		public function ParsingTest(methodName:String)
		{
			super(methodName);
		}
		
		public static function testsuite():TestSuite
		{
			var ts:TestSuite = new TestSuite();
			/*ts.addTest(new ParsingTest("testPlainBeanType"));
			ts.addTest(new ParsingTest("testRefereceType"));
			ts.addTest(new ParsingTest("testMap"));
			ts.addTest(new ParsingTest("testStack"));*/
			ts.addTest(new ParsingTest("testInit"));
			return ts;
		}
		
		public function testPlainBeanType():void
		{
			var config:XML = 
							<beans>
								<bean id="setter0" clazz='cn.geckos.mock.PlainTest'/>
								<bean id='setter' clazz='cn.geckos.mock.PlainTest'>
									<property name='name' value='jeff'/>
									<property name='date' value='2007-7-1'/>
								</bean>
								<bean id='setter2' clazz='cn.geckos.mock.PlainTest' scope='prototype'>
									<property name='name' value='harry'/>
									<property name='date' value='2007-8-1'/>
								</bean>
							</beans>
			var d1:Dictionary = new Dictionary();
			var b5:Bean = new Bean();
			b5.id = "setter0";
			b5.name = "cn.geckos.mock.PlainTest";
			b5.scope = Scope.SINGLETON;
			b5.object = new PlainTest();
			d1["setter0"] = b5
			var b0:Bean = new Bean();
			b0.id = "setter2";
			b0.name = "cn.geckos.mock.PlainTest";
			var pt:PlainTest = new PlainTest();
			pt.date = "2007-8-1";
			pt.name = "harry";
			b0.object = pt;
			b0.scope = Scope.PROTOTYPE;
			d1["setter2"] = b0;
			
			var b:Bean = new Bean();
			b.id = "setter";
			b.name = "cn.geckos.mock.PlainTest";
		 	pt = new PlainTest();
			pt.date = "2007-7-1";
			pt.name = "jeff";
			b.object = pt;
			b.scope = Scope.SINGLETON;
			d1["setter"] = b;
			
			var parser:XMLConfigParser = new XMLConfigParser(config);
			var d2:Dictionary = parser.parse();
			
			var b1:Bean = d1["setter"] as Bean;
			var b2:Bean = d2["setter"] as Bean;
			
			assertTrue(b1.equals(b2));
			var o1:PlainTest = b1.object as PlainTest;
			var o2:PlainTest = b2.object as PlainTest;
			assertTrue(o1.equals(o2));
			
			var b3:Bean = d1["setter2"] as Bean;
			var b4:Bean = d2["setter2"] as Bean;
			
			assertTrue(b4.equals(b3));
			var o3:PlainTest = b3.object as PlainTest;
			var o4:PlainTest = b4.object as PlainTest;
			assertTrue(o3.equals(o4));
			
			var b6:Bean = d1["setter0"] as Bean;
			var b7:Bean = d2["setter0"] as Bean;
			
			assertTrue(b6.equals(b7));
			var o5:PlainTest = b6.object as PlainTest;
			var o6:PlainTest = b7.object as PlainTest;
			assertTrue(o5.equals(o6));
		} 
		
		public function testRefereceType():void
		{
			var config:XML = 
							<beans>
								<bean id="test" clazz="cn.geckos.mock.ReferenceTypeMock">
									<property name="plain">
										<ref bean="pt"/>
									</property>
								</bean>
								<bean id="pt" clazz="cn.geckos.mock.PlainTest">
									<property name="name" value="jeff"/>
									<property name="date" value="2007-7-1"/>
								</bean>
								
								<bean id="pt1" clazz="cn.geckos.mock.PlainTest" scope="prototype">
									<property name="name" value="jeff"/>
									<property name="date" value="2007-7-1"/>
								</bean>
								<bean id="test1" clazz="cn.geckos.mock.ReferenceTypeMock">
									<property name="plain">
										<ref bean="pt1"/>
									</property>
								</bean>
								<bean id="test2" clazz="cn.geckos.mock.ReferenceTypeMock">
									<property name="plain" ref='pt1'/>
								</bean>
							</beans>;
			// 测试当被引用的是singleton时
			var d1:Dictionary = new Dictionary();
			var p1:PlainTest = new PlainTest();
			p1.date = "2007-7-1";
			p1.name = "jeff";
			var t1:ReferenceTypeMock = new ReferenceTypeMock();
			t1.plain=p1;
			var b1:Bean = new Bean();
			b1.id = "pt";
			b1.name = "cn.geckos.mock.PlainTest";
			b1.object = p1;
			b1.scope = Scope.SINGLETON;
			var b2:Bean = new Bean();
			b2.id = "test";
			b2.name = "cn.geckos.mock.ReferenceTypeMock";
			b2.object = t1;
			b2.scope = Scope.SINGLETON;
			d1["pt"] = b1;
			d1["test"] = b2;
			
			var parser:XMLConfigParser = new XMLConfigParser(config);
			var d2:Dictionary = parser.parse();
			
			var g1:Bean = d1["test"] as Bean;
			var g2:Bean = d2["test"] as Bean;
			
			assertTrue(g1.equals(g2));
			var o1:PlainTest = (g1.object as ReferenceTypeMock).plain as PlainTest;
			var o2:PlainTest = (g2.object as ReferenceTypeMock).plain as PlainTest;
			assertTrue(o1.equals(o2));
			
			// 测试当被引用的是prototype时
			p1 = new PlainTest();
			p1.date = "2007-7-1";
			p1.name = "jeff";
			t1 = new ReferenceTypeMock();
			t1.plain=p1;
			b1 = new Bean();
			b1.id = "pt1";
			b1.name = "cn.geckos.mock.PlainTest";
			b1.object = p1;
			b1.scope = Scope.PROTOTYPE;
			b2 = new Bean();
			b2.id = "test1";
			b2.name = "cn.geckos.mock.ReferenceTypeMock";
			b2.object = t1;
			b2.scope = Scope.SINGLETON;
			d1["pt1"] = b1;
			d1["test1"] = b2;
			
			g1 = d1["test1"] as Bean;
			g2 = d2["test1"] as Bean;
			var g3:Bean = d2["test2"] as Bean;
			
			assertTrue(g1.equals(g2));
			o1 = (g1.object as ReferenceTypeMock).plain;
			o2 = (g2.object as ReferenceTypeMock).plain;
			assertTrue(o1.equals(o2));
			
			//assertTrue(g3.equals(g1));
			o1 = (g3.object as ReferenceTypeMock).plain;
			o2 = (g1.object as ReferenceTypeMock).plain;
			assertTrue(o1.equals(o2));
		}
		
		public function testMap():void
		{
			var config:XML = 
							<beans>
								<bean id="pt" clazz="cn.geckos.mock.PlainTest" scope="prototype">
									<property name="name" value="jeff"/>
									<property name="date" value="2007-7-1"/>
								</bean>
								<bean id='test' clazz='cn.geckos.mock.MapMock'>
									<property name='map'>
										<map>
											<entry>
												<key value='hi'/>
												<value>hello</value>
											</entry>
											<entry>
												<key value='re'/>
												<ref bean='pt'/>
											</entry>
										</map>
									</property>
								</bean>
							</beans>
			var d1:Dictionary = new Dictionary();
			
			var p1:PlainTest = new PlainTest();
			p1.date = "2007-7-1";
			p1.name = "jeff";
			var m1:MapMock = new MapMock();
			var v1:Dictionary = new Dictionary();
			v1["hi"] = "hello";
			v1["re"] = p1;
			m1.map=v1;
			var b1:Bean = new Bean();
			b1.id = "pt";
			b1.name = "cn.geckos.mock.PlainTest";
			b1.object = p1;
			b1.scope = Scope.SINGLETON;
			var b2:Bean = new Bean();
			b2.id = "test1";
			b2.name = "cn.geckos.mock.MapMock";
			b2.object = m1;
			b2.scope = Scope.SINGLETON;
			d1["pt"] = b1;
			d1["test"] = b2;
			
			var parser:XMLConfigParser = new XMLConfigParser(config);
			var d2:Dictionary = parser.parse();
			
			var g1:Bean = d1["test"] as Bean;
			var g2:Bean = d2["test"] as Bean;
			
			var o1:MapMock = g1.object as MapMock;
			var o2:MapMock = g2.object as MapMock;
			trace("=======");
			var m:Dictionary = o1.map;
			for(var i:Object in m)
			{
				trace([i,m[i]]);
			}
			trace("=======");
			m = o2.map;
			for(i in m)
			{
				trace([i,m[i]]);
			}
			trace("=======");
			var dd1:Dictionary = o1.map;
			var dd2:Dictionary = o2.map;
			assertTrue(dd1["re"].equals(dd2["re"]));
		}
		
		public function testStack():void
		{
			var config:XML = 
							<beans>
								<bean id="pt" clazz="cn.geckos.mock.PlainTest" scope="prototype">
									<property name="name" value="jeff"/>
									<property name="date" value="2007-7-1"/>
								</bean>
								<bean id='test' clazz='cn.geckos.mock.StackMock'>
									<property name='array'>
										<stack>
											<value>hi</value>
											<ref bean='pt'/>
										</stack>
									</property>
								</bean>
							</beans>
							
			var d1:Dictionary = new Dictionary();
			
			var p1:PlainTest = new PlainTest();
			p1.date = "2007-7-1";
			p1.name = "jeff";
			var a1:Array = new Array();
			a1.push("hi");
			a1.push(p1);
			var sm:StackMock = new StackMock();
			sm.array=a1;
			var b1:Bean = new Bean();
			b1.id = "pt";
			b1.name = "cn.geckos.mock.PlainTest";
			b1.object = p1;
			b1.scope = Scope.SINGLETON;
			var b2:Bean = new Bean();
			b2.id = "test";
			b2.name = "cn.geckos.mock.StackMock";
			b2.object = sm;
			b2.scope = Scope.SINGLETON;
			d1["pt"] = b1;
			d1["test"] = b2;
			
			var parser:XMLConfigParser = new XMLConfigParser(config);
			var d2:Dictionary = parser.parse();
			
			var g1:Bean = d1["test"] as Bean;
			var g2:Bean = d2["test"] as Bean;
			
			var o1:StackMock = g1.object as StackMock;
			var o2:StackMock = g2.object as StackMock;
			
			var aa1:Array = o1.array;
			var aa2:Array = o2.array;
			
			assertTrue(aa1[0] == aa2[0]);
			assertTrue(aa1[1].equals(aa2[1]));
		}
		
		public function testInit():void
		{
			var config:XML = 
							<beans>
								<bean id='abc' clazz='cn.geckos.mock.InitMock' init='initFun' scope='prototype'/>
								<bean id='abd' clazz='cn.geckos.mock.InitMock' init='initFun' scope='prototype'/>
							</beans>
			var parser:XMLConfigParser = new XMLConfigParser(config);
			parser.parse();
			var b:InitMock = parser.getBean("abd");
			assertTrue(b.a == "ok");
		}
	}
}